<template><div><p>本文档最新版为 <a href="https://learnku.com/docs/laravel/10.x" target="_blank" rel="noopener noreferrer">10.x</a>，旧版本可能放弃维护，推荐阅读最新版！</p>
<h2 id="广播系统" tabindex="-1"><a class="header-anchor" href="#广播系统"><span>广播系统</span></a></h2>
<ul>
<li><a href="#introduction">简介</a>
<ul>
<li><a href="#configuration">配置</a></li>
<li><a href="#concept-overview">对驱动的要求</a></li>
</ul>
</li>
<li><a href="#concept-overview">概念综述</a>
<ul>
<li><a href="#using-example-application">使用示例程序</a></li>
</ul>
</li>
<li><a href="#defining-broadcast-events">定义广播事件</a>
<ul>
<li><a href="#broadcast-name">广播名称</a></li>
<li><a href="#broadcast-data">广播数据</a></li>
<li><a href="#broadcast-queue">广播队列</a></li>
<li><a href="#broadcast-conditions">广播条件</a></li>
</ul>
</li>
<li><a href="#authorizing-channels">授权频道</a>
<ul>
<li><a href="#defining-authorization-routes">定义授权路由</a></li>
<li><a href="#defining-authorization-callbacks">定义授权回调</a></li>
<li><a href="#defining-channel-classes">定义频道类</a></li>
</ul>
</li>
<li><a href="#broadcasting-events">广播事件</a>
<ul>
<li><a href="#only-to-others">只广播给他人</a></li>
</ul>
</li>
<li><a href="#receiving-broadcasts">接收广播</a>
<ul>
<li><a href="#installing-laravel-echo">安装 Laravel Echo</a></li>
<li><a href="#listening-for-events">对事件进行监听</a></li>
<li><a href="#leaving-a-channel">退出频道</a></li>
<li><a href="#namespaces">命名空间</a></li>
</ul>
</li>
<li><a href="#presence-channels">Presence 频道</a>
<ul>
<li><a href="#authorizing-presence-channels">授权 Presence 频道</a></li>
<li><a href="#joining-presence-channels">加入 Presence 频道</a></li>
<li><a href="#broadcasting-to-presence-channels">广播到 Presence 频道</a></li>
</ul>
</li>
<li><a href="#client-events">客户端事件</a></li>
<li><a href="#notifications">消息通知</a></li>
</ul>
<h2 id="简介" tabindex="-1"><a class="header-anchor" href="#简介"><span>简介</span></a></h2>
<p>在现代的 web 应用程序中， WebSockets 被用来实现实时、即时更新的用户接口。当服务器上的数据更新后，更新信息会通过 WebSocket 连接发送到客户端等待处理。相比于不停地轮询应用程序，这是一种更加可靠和高效的选择。</p>
<p>为了帮助你构建这类应用， Laravel 将通过 WebSocket 连接来使「广播」 事件 变得更加轻松。 广播 Laravel 事件允许你在服务端和客户端 JavaScript 应用程序间共享相同的事件名。</p>
<blockquote>
<p>{注} 在深入了解事件广播之前，请确认你已阅读所有关于 Laravel <a href="https://learnku.com/docs/laravel/6.x/events" target="_blank" rel="noopener noreferrer">事件和监听器</a> 的文档</p>
</blockquote>
<h3 id="配置" tabindex="-1"><a class="header-anchor" href="#配置"><span>配置</span></a></h3>
<p>所有关于事件广播的配置都保存在 <code v-pre>config/broadcasting.php</code> 配置文件中。 Laravel 自带了几个广播驱动： <a href="https://pusher.com/channels" target="_blank" rel="noopener noreferrer">Pusher</a> 、 <a href="https://learnku.com/docs/laravel/6.x/redis" target="_blank" rel="noopener noreferrer">Redis</a> ， 和一个用于本地开发与调试的 <code v-pre>log</code>驱动。另外，还有一个<code v-pre>null</code> 驱动允许你完全关闭广播系统。每一个驱动的示例配置都可以在 <code v-pre>config/broadcasting.php</code> 配置文件中找到。</p>
<h4 id="对驱动的要求" tabindex="-1"><a class="header-anchor" href="#对驱动的要求"><span>对驱动的要求</span></a></h4>
<p>在对事件进行广播之前，你必须先注册 <code v-pre>App\Providers\BroadcastServiceProvider</code> 。对于一个新建的 Laravel 应用程序，你只需要在 <code v-pre>config/app.php</code> 配置文件的 <code v-pre>providers</code> 数组中取消对该提供者的注释即可。该提供者将允许你注册广播授权路由和回调。</p>
<h4 id="csrf-令牌" tabindex="-1"><a class="header-anchor" href="#csrf-令牌"><span>CSRF 令牌</span></a></h4>
<p><a href="#installing-laravel-echo">Laravel Echo</a> 需要访问当前会话的 CSRF 令牌。你应当验证你的应用程序的 <code v-pre>head</code> HTML 元素是否定义了包含 CSRF 令牌的 <code v-pre>meta</code> 标签：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token operator">&lt;</span>meta name<span class="token operator">=</span><span class="token string double-quoted-string">"csrf-token"</span> content<span class="token operator">=</span><span class="token string double-quoted-string">"{{ csrf_token() }}"</span><span class="token operator">></span> </span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="对驱动的要求-1" tabindex="-1"><a class="header-anchor" href="#对驱动的要求-1"><span>对驱动的要求</span></a></h3>
<h4 id="pusher" tabindex="-1"><a class="header-anchor" href="#pusher"><span>Pusher</span></a></h4>
<p>如果你使用 <a href="https://pusher.com/channels" target="_blank" rel="noopener noreferrer">Pusher</a> 来对事件进行广播，请用 Composer 包管理器来安装 Pusher PHP SDK ：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">composer <span class="token keyword">require</span> pusher<span class="token operator">/</span>pusher<span class="token operator">-</span>php<span class="token operator">-</span>server <span class="token string double-quoted-string">"~4.0"</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>然后，你需要在 <code v-pre>config/broadcasting.php</code> 配置文件中配置你的 Pusher 证书。该文件中已经包含了一个 Pusher 示例配置，你可以快速地指定你的 <code v-pre>Pusher key</code> 、<code v-pre>secret</code> 和 <code v-pre>application ID</code>。 <code v-pre>config/broadcasting.php</code> 文件的 <code v-pre>pusher</code>配置项同时也允许你指定 Pusher 支持的额外 <code v-pre>options</code> ，例如 <code v-pre>cluster</code>：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token string single-quoted-string">'options'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'cluster'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'eu'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'useTLS'</span> <span class="token operator">=></span> <span class="token constant boolean">true</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>当 <code v-pre>Channels</code> 和 <a href="#installing-laravel-echo"><code v-pre>Laravel Echo</code></a> 一起使用时，你应该在 <code v-pre>resources/js/bootstrap.js</code> 文件中实例化 Echo 对象时指定 <code v-pre>pusher</code> 作为所需要的 <code v-pre>broadcaster</code> ：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">import <span class="token keyword">Echo</span> from <span class="token string double-quoted-string">"laravel-echo"</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">window<span class="token operator">.</span>Pusher <span class="token operator">=</span> <span class="token keyword">require</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'pusher-js'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">window<span class="token operator">.</span><span class="token keyword">Echo</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">Echo</span><span class="token punctuation">(</span><span class="token punctuation">{</span></span>
<span class="line">    broadcaster<span class="token punctuation">:</span> <span class="token string single-quoted-string">'pusher'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token argument-name">key</span><span class="token punctuation">:</span> <span class="token string single-quoted-string">'your-pusher-channels-key'</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="redis" tabindex="-1"><a class="header-anchor" href="#redis"><span>Redis</span></a></h4>
<p>如果你使用 Redis 广播器，请安装 Predis 库：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">composer <span class="token keyword">require</span> predis<span class="token operator">/</span>predis</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>Redis 广播器会使用 Redis 的 发布 / 订阅 特性来广播消息；尽管如此，你仍需将它与能够从 Redis 接收消息的 WebSocket 服务器配对使用以便将消息广播到你的 WebSocket 频道上去。</p>
<p>当 Redis 广播器发布一个事件的时候，该事件会被发布到它指定的频道上去，传输的数据是一个采用 JSON 编码的字符串。该字符串包含了事件名、 <code v-pre>data</code> 数据和生成该事件 socket ID 的用户（如果可用的话）。</p>
<h4 id="socket-io" tabindex="-1"><a class="header-anchor" href="#socket-io"><span>Socket.IO</span></a></h4>
<p>如果你想将 Redis 广播器 和 Socket.IO 服务器进行配对，你需要在你的应用程序中引入 Socket.IO JavaScript 客户端库。你可以通过 NPM 包管理器进行安装：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">npm install <span class="token operator">--</span>save socket<span class="token operator">.</span>io<span class="token operator">-</span>client</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>然后，你需要在实例化 <code v-pre>Echo</code> 时指定 <code v-pre>socket.io</code> 连接器和 <code v-pre>host</code> 。</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">import <span class="token keyword">Echo</span> from <span class="token string double-quoted-string">"laravel-echo"</span></span>
<span class="line"></span>
<span class="line">window<span class="token operator">.</span>io <span class="token operator">=</span> <span class="token keyword">require</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'socket.io-client'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">window<span class="token operator">.</span><span class="token keyword">Echo</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">Echo</span><span class="token punctuation">(</span><span class="token punctuation">{</span></span>
<span class="line">    broadcaster<span class="token punctuation">:</span> <span class="token string single-quoted-string">'socket.io'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token argument-name">host</span><span class="token punctuation">:</span> window<span class="token operator">.</span>location<span class="token operator">.</span>hostname <span class="token operator">+</span> <span class="token string single-quoted-string">':6001'</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>最后，你需要运行一个与 Laravel 兼容的 Socket.IO 服务器。 Laravel 官方并没有内置 Socket.IO 服务器实现；不过，可以选择一个由社区驱动维护的项目 <a href="https://github.com/tlaverdure/laravel-echo-server" target="_blank" rel="noopener noreferrer">tlaverdure/laravel-echo-server</a> ，目前托管在 GitHub 。</p>
<h4 id="对队列的要求" tabindex="-1"><a class="header-anchor" href="#对队列的要求"><span>对队列的要求</span></a></h4>
<p>在开始广播事件之前，你还需要配置和运行 <a href="https://learnku.com/docs/laravel/6.x/queues" target="_blank" rel="noopener noreferrer">队列监听器</a> 。所有的事件广播都是通过队列任务来完成的，因此应用程序的响应时间不会受到明显影响。</p>
<h2 id="概念综述" tabindex="-1"><a class="header-anchor" href="#概念综述"><span>概念综述</span></a></h2>
<p>Laravel 的事件广播允许你使用基于驱动的 WebSockets 将服务端的 Laravel 事件广播到客户端的 JavaScript 应用程序。当前的 Laravel 自带了 <a href="https://pusher.com/channels" target="_blank" rel="noopener noreferrer">Pusher</a> 和 Redis 驱动。通过使用 <a href="#installing-laravel-echo">Laravel Echo</a> 的 Javascript 包，我们可以很方便地在客户端消费事件。</p>
<p>事件通过「频道」来广播，这些频道可以被指定为公开或私有的。任何访客都可以不经授权或认证订阅一个公开频道；然而，如果想要订阅一个私有频道，那么该用户必须通过认证，并获得该频道的授权。</p>
<h3 id="使用示例程序" tabindex="-1"><a class="header-anchor" href="#使用示例程序"><span>使用示例程序</span></a></h3>
<p>深入了解事件广播的每个组件之前，让我们先用一个电子商务网站作为例子来概览一下。我们不会讨论配置 <a href="https://pusher.com/channels" target="_blank" rel="noopener noreferrer">Pusher</a> 或者 <a href="#installing-laravel-echo">Laravel Echo</a> 的细节，这些会在本文档的其它章节里详细讨论。</p>
<p>在我们的应用程序中，我们假设有一个允许用户查看订单配送状态的页面。有一个 <code v-pre>ShippingStatusUpdated</code> 事件会在配送状态更新时被触发：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token function">event</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">ShippingStatusUpdated</span><span class="token punctuation">(</span><span class="token variable">$update</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="shouldbroadcast-接口" tabindex="-1"><a class="header-anchor" href="#shouldbroadcast-接口"><span><code v-pre>ShouldBroadcast</code> 接口</span></a></h4>
<p>当用户在查看自己的订单时，我们不希望他们必须通过刷新页面才能看到状态更新。我们希望一旦有更新时就主动将更新信息广播到客户端。所以，我们必须标记 <code v-pre>ShippingStatusUpdated</code> 事件实现 <code v-pre>ShouldBroadcast</code> 接口。这会让 Laravel 在事件被触发时广播该事件：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Events</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>Channel</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Queue<span class="token punctuation">\</span>SerializesModels</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>PrivateChannel</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>PresenceChannel</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>InteractsWithSockets</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Contracts<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>ShouldBroadcast</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">ShippingStatusUpdated</span> <span class="token keyword">implements</span> <span class="token class-name">ShouldBroadcast</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * Information about the shipping status update.</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@var</span> <span class="token class-name"><span class="token keyword">string</span></span></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token variable">$update</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code v-pre>ShouldBroadcast</code> 接口要求事件定义一个 <code v-pre>broadcastOn</code> 方法。该方法负责指定事件被广播到哪些频道。在（通过 Artisan 命令）生成的事件类中，一个空的 <code v-pre>broadcastOn</code> 方法已经被预定义好了，所以我们只需要完成其细节即可。我们希望只有订单的创建者能够看到状态的更新，所以我们要把该事件广播到与这个订单绑定的私有频道上去：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * Get the channels the event should broadcast on.</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@return</span> <span class="token class-name"><span class="token punctuation">\</span>Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>PrivateChannel</span></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">broadcastOn</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">PrivateChannel</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'order.'</span><span class="token operator">.</span><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">update</span><span class="token operator">-></span><span class="token property">order_id</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="授权频道" tabindex="-1"><a class="header-anchor" href="#授权频道"><span>授权频道</span></a></h4>
<p>请记住，只有授权过的用户才可以收听私有频道。我们可以在<code v-pre>routes/channels.php</code> 文件中，定义我们频道的授权规则。 在这个例子中，我们需要去验证任何试图收听 <code v-pre>order.1</code> 私有频道的用户，是否是订单实际上的创建者：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Broadcast</span><span class="token operator">::</span><span class="token function">channel</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'order.{orderId}'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token variable">$user</span><span class="token punctuation">,</span> <span class="token variable">$orderId</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token variable">$user</span><span class="token operator">-></span><span class="token property">id</span> <span class="token operator">===</span> <span class="token class-name static-context">Order</span><span class="token operator">::</span><span class="token function">findOrNew</span><span class="token punctuation">(</span><span class="token variable">$orderId</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token property">user_id</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code v-pre>channel</code> 方法接收两个参数： 频道的名称和一个通过返回 <code v-pre>true</code> 或 <code v-pre>false</code> ，来表示用户是否有权收听该频道的回调函数 。</p>
<p>所有授权回调都将当前经过身份验证的用户作为其第一个参数，并将任何其他通配符参数作为其后续参数。 在这个例子中，我们用 <code v-pre>{orderId}</code> 占位符来通配表示频道名称 &quot;ID&quot; 的部分。</p>
<h4 id="监听事件广播" tabindex="-1"><a class="header-anchor" href="#监听事件广播"><span>监听事件广播</span></a></h4>
<p>接下来， 剩余的工作就是在我们的 JavaScript应用程序中监听事件。 我们可以使用 Laravel Echo 来做到这一点。首先，我们将使用<code v-pre>private</code>方法订阅私有频道。 然后，我们可以使用<code v-pre>listen</code>方法来监听 <code v-pre>ShippingStatusUpdated</code> 事件。 默认情况下，所有事件的公共属性都将包含在广播事件中：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">Echo</span><span class="token operator">.</span><span class="token keyword">private</span><span class="token punctuation">(</span><span class="token string backtick-quoted-string">`order.${orderId}`</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'ShippingStatusUpdated'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        console<span class="token operator">.</span><span class="token function">log</span><span class="token punctuation">(</span>e<span class="token operator">.</span>update<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="定义广播事件" tabindex="-1"><a class="header-anchor" href="#定义广播事件"><span>定义广播事件</span></a></h2>
<p>要通知 Laravel 应该广播给定事件, 并在该事件上实现 <code v-pre>Illuminate\Contracts\Broadcasting\ShouldBroadcast</code> 接口。此接口已导入到框架生成的所有事件类中，因此你可以轻松地将其添加到任何事件中。</p>
<p><code v-pre>ShouldBroadcast</code> 接口要求你实现一个方法： <code v-pre>broadcastOn</code>。 <code v-pre>broadcastOn</code> 方法应该返回事件应该广播的频道或频道数组。 该频道应该是 <code v-pre>Channel</code>，<code v-pre>PrivateChannel</code>，或者 <code v-pre>PresenceChannel</code> 的实例. 。<code v-pre>Channel</code> 的实例 代表任何用户可以订阅的公共频道， <code v-pre>PrivateChannels</code> 和 <code v-pre>PresenceChannels</code> 实列代表需要<a href="#authorizing-channels">频道授权</a>的私有频道：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Events</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>User</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>Channel</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Queue<span class="token punctuation">\</span>SerializesModels</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>PrivateChannel</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>PresenceChannel</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>InteractsWithSockets</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Contracts<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>ShouldBroadcast</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">ServerCreated</span> <span class="token keyword">implements</span> <span class="token class-name">ShouldBroadcast</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">use</span> <span class="token package">SerializesModels</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">public</span> <span class="token variable">$user</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 新建一个新的事件实例</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">void</span></span></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">__construct</span><span class="token punctuation">(</span><span class="token class-name type-declaration">User</span> <span class="token variable">$user</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">user</span> <span class="token operator">=</span> <span class="token variable">$user</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 获取事件应广播的频道。</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@return</span> <span class="token class-name">Channel<span class="token punctuation">|</span><span class="token keyword">array</span></span></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">broadcastOn</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">PrivateChannel</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'user.'</span><span class="token operator">.</span><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">user</span><span class="token operator">-></span><span class="token property">id</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>那么， 你仅仅需要像平常那样 <a href="https://learnku.com/docs/laravel/6.x/events" target="_blank" rel="noopener noreferrer">触发事件</a> 。事件一旦触发， 一个 <a href="https://learnku.com/docs/laravel/6.x/queues" target="_blank" rel="noopener noreferrer">队列任务</a> 将通过你指定的广播驱动程序广播该事件。</p>
<h3 id="广播名称" tabindex="-1"><a class="header-anchor" href="#广播名称"><span>广播名称</span></a></h3>
<p>通常，Laravel 将通过事件类的名称广播该事件，但是， 你也可以通过在事件中定义一个 <code v-pre>broadcastAs</code> 方法，来自定义事件名称：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 广播事件名称</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">string</span></span></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">broadcastAs</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token string single-quoted-string">'server.created'</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果你通过 <code v-pre>broadcastAs</code> 方法自定义广播名称， 你应该确保使用了一个前导的 <code v-pre>.</code> 字符，注册了你的监听器。 这将指示 Echo 不要将应用程序的命名空间添加到事件中：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token operator">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'.server.created'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token operator">...</span><span class="token operator">.</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="广播数据" tabindex="-1"><a class="header-anchor" href="#广播数据"><span>广播数据</span></a></h3>
<p>当一个事件被广播时， 它的所有<code v-pre>public</code>属性都会被自动序列化并作为事件的有效负载进行广播，这允许你从JavaScript应用程序访问它的任何公共数据。所以，例如，如果你的事件有一个包含 Eloquent 模型的公共 <code v-pre>$user</code> 属性， 该事件广播载入内容将如下所示：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token string double-quoted-string">"user"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token string double-quoted-string">"id"</span><span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string double-quoted-string">"name"</span><span class="token punctuation">:</span> <span class="token string double-quoted-string">"Patrick Stewart"</span></span>
<span class="line">        <span class="token operator">...</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>但是，如果你希望对广播载入的内容进行更细粒度的控制，可以在事件中添加 <code v-pre>broadcastWith</code> 方法。 此方法将返回一个数据数组作为你希望广播事件所载入的内容：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 获取广播数据</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">array</span></span></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">broadcastWith</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'id'</span> <span class="token operator">=></span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">user</span><span class="token operator">-></span><span class="token property">id</span><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="广播队列" tabindex="-1"><a class="header-anchor" href="#广播队列"><span>广播队列</span></a></h3>
<p>通常， 在你的 <code v-pre>queue.php</code> 配置文件中， 每个广播事件都放在指定默认队列连接的默认队列中。你可以在事件类中定义一个 <code v-pre>broadcastQueue</code> 属性来自定义广播的队列。此属性应指定广播时你要使用队列的名称：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 要放置事件的队列的名称。</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@var</span> <span class="token class-name"><span class="token keyword">string</span></span></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token variable">$broadcastQueue</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'your-queue-name'</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>假如你要使用 <code v-pre>sync</code> 队列驱动代替默认的队列驱动来广播事件，你可以通过继承 <code v-pre>ShouldBroadcastNow</code> 接口来替代 <code v-pre>ShouldBroadcast</code>接口：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Contracts<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>ShouldBroadcastNow</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">ShippingStatusUpdated</span> <span class="token keyword">implements</span> <span class="token class-name">ShouldBroadcastNow</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">//</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="广播条件" tabindex="-1"><a class="header-anchor" href="#广播条件"><span>广播条件</span></a></h3>
<p>有时候你需要在给定条件为 true 的时候才广播事件，你可以在事件类中增加一个 <code v-pre>broadcastWhen</code> 方法去定义这些条件：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 确定事件是否要被广播</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">bool</span></span></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">broadcastWhen</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">value</span> <span class="token operator">></span> <span class="token number">100</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="授权频道-1" tabindex="-1"><a class="header-anchor" href="#授权频道-1"><span>授权频道</span></a></h2>
<p>私人频道往往需要授权验证过的用户才可以实际收听该频道。这是通过使用频道名称向你的 Laravel 应用程序发出 HTTP 请求，并允许你的应用程序确定用户是否可以收听该频道来实现的。使用 <a href="#installing-laravel-echo">Laravel Echo</a>时， 将自动进行授权订阅私人频道的HTTP请求；但是，你需要定义响应这些请求的正确路由。</p>
<h3 id="定义授权路由" tabindex="-1"><a class="header-anchor" href="#定义授权路由"><span>定义授权路由</span></a></h3>
<p>庆幸的是，Laravel 可以轻松定义响应频道授权请求的路由。在 Laravel 应用程序附带的 <code v-pre>BroadcastServiceProvider</code>中，你将看到对 <code v-pre>Broadcast :: routes</code> 方法的调用。 此方法将注册 <code v-pre>/broadcasting/auth</code> 路由去处理授权请求：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Broadcast</span><span class="token operator">::</span><span class="token function">routes</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p><code v-pre>Broadcast::routes</code> 方法将自动将其路由放在 <code v-pre>web</code> 中间件组中； 但是，如果要自定义指定的属性，可以将路径属性数组传递给方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Broadcast</span><span class="token operator">::</span><span class="token function">routes</span><span class="token punctuation">(</span><span class="token variable">$attributes</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="自定义授权端点" tabindex="-1"><a class="header-anchor" href="#自定义授权端点"><span>自定义授权端点</span></a></h4>
<p>通常， Echo 会使用 <code v-pre>/broadcasting/auth</code> 端点来授权频道访问。 但是，你可以通过将 <code v-pre>authEndpoint</code> 配置选项传递给 Echo 实例来指定自己的授权端点：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">window<span class="token operator">.</span><span class="token keyword">Echo</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">Echo</span><span class="token punctuation">(</span><span class="token punctuation">{</span></span>
<span class="line">    broadcaster<span class="token punctuation">:</span> <span class="token string single-quoted-string">'pusher'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token argument-name">key</span><span class="token punctuation">:</span> <span class="token string single-quoted-string">'your-pusher-channels-key'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token argument-name">authEndpoint</span><span class="token punctuation">:</span> <span class="token string single-quoted-string">'/custom/endpoint/auth'</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="定义授权回调" tabindex="-1"><a class="header-anchor" href="#定义授权回调"><span>定义授权回调</span></a></h3>
<p>接下来，我们需要定义实际执行频道授权的逻辑。这是在你的应用程序附带的 <code v-pre>routes/channels.php</code> 文件中完成的 。 在这个文件中，你可以使用<code v-pre>Broadcast::channel</code> 方法注册频道授权回调：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Broadcast</span><span class="token operator">::</span><span class="token function">channel</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'order.{orderId}'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token variable">$user</span><span class="token punctuation">,</span> <span class="token variable">$orderId</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token variable">$user</span><span class="token operator">-></span><span class="token property">id</span> <span class="token operator">===</span> <span class="token class-name static-context">Order</span><span class="token operator">::</span><span class="token function">findOrNew</span><span class="token punctuation">(</span><span class="token variable">$orderId</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token property">user_id</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code v-pre>channel</code> 方法接受两个参数：频道的名称和返回 <code v-pre>true</code> 或 <code v-pre>false</code> 来指示用户是否有权在频道上进行侦听的回调。</p>
<p>所有授权回调都将当前经过身份验证的用户作为其第一个参数，并将任何其他通配符参数作为其后续参数。 在这个例子中，我们用 <code v-pre>{orderId}</code> 占位符来通配表示频道名称 &quot;ID&quot; 的部分。</p>
<h4 id="授权回调模型绑定" tabindex="-1"><a class="header-anchor" href="#授权回调模型绑定"><span>授权回调模型绑定</span></a></h4>
<p>就像 HTTP 路由一样， 频道路由可以利用隐式和显式 <a href="https://learnku.com/docs/laravel/6.x/routing#route-model-binding" target="_blank" rel="noopener noreferrer">路由模型绑定</a>.。例如，你可以请求一个实际的<code v-pre>Order</code> 模型实列来替代接收一个字符串或者订单 ID 数字：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Order</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Broadcast</span><span class="token operator">::</span><span class="token function">channel</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'order.{order}'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token variable">$user</span><span class="token punctuation">,</span> <span class="token class-name type-declaration">Order</span> <span class="token variable">$order</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token variable">$user</span><span class="token operator">-></span><span class="token property">id</span> <span class="token operator">===</span> <span class="token variable">$order</span><span class="token operator">-></span><span class="token property">user_id</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="授权回调验证" tabindex="-1"><a class="header-anchor" href="#授权回调验证"><span>授权回调验证</span></a></h4>
<p>私有和在线广播频道，通过应用程序默认的认证防护器来认证当前用户。如果用户未经过认证，则会自动拒绝频道授权，并且永远不会执行授权回调。 但是，你可以分配多个自定义防护器，以便在必要时对传入请求进行身份验证：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Broadcast</span><span class="token operator">::</span><span class="token function">channel</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'channel'</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'guards'</span> <span class="token operator">=></span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'web'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'admin'</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="定义频道类" tabindex="-1"><a class="header-anchor" href="#定义频道类"><span>定义频道类</span></a></h3>
<p>如果你的应用程序使用了很多不同的频道， 那么 <code v-pre>routes/channels.php</code> 文件将会变得很臃肿。 所以，你可以使用频道类，而不是使用闭包来授权频道。要生成频道类，使用 <code v-pre>make:channel</code> Artisan 命令。 此命令将在 <code v-pre>App/Broadcasting</code> 目录，生成一个新的频道类。</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">php artisan make<span class="token punctuation">:</span>channel OrderChannel</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>接下来，在 <code v-pre>routes/channels.php</code> 文件中注册你的频道：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>OrderChannel</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Broadcast</span><span class="token operator">::</span><span class="token function">channel</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'order.{order}'</span><span class="token punctuation">,</span> <span class="token class-name static-context">OrderChannel</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>最后，你可以把频道的授权逻辑，放在频道类的 <code v-pre>join</code> 方法中。<code v-pre>join</code> 方法将保留在频道授权闭包中的逻辑。 你还可以利用频道模型绑定：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Broadcasting</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>User</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Order</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">OrderChannel</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     *新建一个新的频道实例</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">void</span></span></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">__construct</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">//</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 验证用户对频道的访问权限。</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@param</span>  <span class="token class-name"><span class="token punctuation">\</span>App<span class="token punctuation">\</span>User</span>  <span class="token parameter">$user</span></span>
<span class="line">     * <span class="token keyword">@param</span>  <span class="token class-name"><span class="token punctuation">\</span>App<span class="token punctuation">\</span>Order</span>  <span class="token parameter">$order</span></span>
<span class="line">     * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">array</span><span class="token punctuation">|</span><span class="token keyword">bool</span></span></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">join</span><span class="token punctuation">(</span><span class="token class-name type-declaration">User</span> <span class="token variable">$user</span><span class="token punctuation">,</span> <span class="token class-name type-declaration">Order</span> <span class="token variable">$order</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token variable">$user</span><span class="token operator">-></span><span class="token property">id</span> <span class="token operator">===</span> <span class="token variable">$order</span><span class="token operator">-></span><span class="token property">user_id</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p>{提示} 和很多 Laravel 中其他类一样，频道类会被 <a href="https://learnku.com/docs/laravel/6.x/container" target="_blank" rel="noopener noreferrer">服务容器</a> 自动解析。 所以，你可以在构造函数中键入频道所需的任何依赖。</p>
</blockquote>
<h2 id="广播事件" tabindex="-1"><a class="header-anchor" href="#广播事件"><span>广播事件</span></a></h2>
<p>一旦你定义了一个事件并用 <code v-pre>ShouldBroadcast</code> 接口标记它，你只需要使用<code v-pre>event</code> 函数来触发事件。 事件调度程序将注意到事件标记为<code v-pre>ShouldBroadcast</code>接口，并将事件排队以进行广播：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token function">event</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">ShippingStatusUpdated</span><span class="token punctuation">(</span><span class="token variable">$update</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="只广播给他人" tabindex="-1"><a class="header-anchor" href="#只广播给他人"><span>只广播给他人</span></a></h3>
<p>在构建利用事件广播的应用程序时，你可以使用<code v-pre>broadcast</code>函数替换<code v-pre>event</code>函数。 与<code v-pre>event</code>函数一样，<code v-pre>broadcast</code>函数将事件调度到服务器端侦听器：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token function">broadcast</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">ShippingStatusUpdated</span><span class="token punctuation">(</span><span class="token variable">$update</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>但是，<code v-pre>broadcast</code> 函数还开放了<code v-pre>toOthers</code>方法，该方法允许你从广播的收件人中排除当前用户：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token function">broadcast</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">ShippingStatusUpdated</span><span class="token punctuation">(</span><span class="token variable">$update</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">toOthers</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>为了更好地理解何时可能需要使用<code v-pre>toOthers</code>方法，让我们设想一个任务列表应用程序，用户可以通过输入任务名称来创建新任务。 要创建任务，你的应用程序可能会向<code v-pre>/task</code>端点发出请求，该端点广播任务的创建并返回JSON 格式的新任务。 当你的 JavaScript 应用程序从端点收到响应时，它可能会直接将新任务插入其任务列表中，如下所示：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">axios<span class="token operator">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/task'</span><span class="token punctuation">,</span> task<span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span>response<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        this<span class="token operator">.</span>tasks<span class="token operator">.</span><span class="token function">push</span><span class="token punctuation">(</span>response<span class="token operator">.</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>但是，请记住，我们还广播任务的创建。 如果你的 JavaScript 应用程序正在收听此事件以便将任务添加到任务列表，则列表中将出现重复的任务：一个来自端点，另一个来自广播。 你可以使用<code v-pre>toOthers</code>方法来指示广播器不向当前用户广播事件。</p>
<blockquote>
<p>{注意} 你的事件必须使用 <code v-pre>Illuminate\Broadcasting\InteractsWithSockets</code> trait 才能调用 <code v-pre>toOthers</code> 方法。</p>
</blockquote>
<h4 id="配置-1" tabindex="-1"><a class="header-anchor" href="#配置-1"><span>配置</span></a></h4>
<p>初始化 Laravel Echo 实例时，会为连接分配套接字 ID 。 如果你使用 <a href="https://vuejs.org/" target="_blank" rel="noopener noreferrer">Vue</a> 和 <a href="https://github.com/mzabriskie/axios" target="_blank" rel="noopener noreferrer">Axios</a> ，套接字ID 将自动作为 <code v-pre>X-Socket-ID</code>标题 附加到每个传出请求。 然后，当你调用<code v-pre>toOthers</code>方法时，Laravel 将从标头中提取套接字 ID，并指示广播器不要广播到具有该套接字 ID 的任何连接。</p>
<p>如果你不使用 Vue 和 Axios ，则需要手动配置 JavaScript 应用程序以发送 <code v-pre>X-Socket-ID</code> 头。 你可以使用 <code v-pre>Echo.socketId</code>方法检索套接字ID：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">var</span> socketId <span class="token operator">=</span> <span class="token keyword">Echo</span><span class="token operator">.</span><span class="token function">socketId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h2 id="接收广播" tabindex="-1"><a class="header-anchor" href="#接收广播"><span>接收广播</span></a></h2>
<h3 id="安装-laravel-echo" tabindex="-1"><a class="header-anchor" href="#安装-laravel-echo"><span>安装 Laravel Echo</span></a></h3>
<p>Laravel Echo 是一个 JavaScript 库，可以轻松订阅频道并收听 Laravel 广播的事件。 你可以通过 NPM 包管理器安装 Echo。 在这个例子中，我们还将安装<code v-pre>pusher-js</code> 包，因为我们将使用 Pusher Channels 广播器：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">npm install <span class="token operator">--</span>save laravel<span class="token operator">-</span><span class="token keyword">echo</span> pusher<span class="token operator">-</span>js</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>安装Echo后，你就可以在应用程序的 JavaScript 中创建一个全新的 Echo 实例。 一个好的实现方式是将它放在 Laravel 框架附带的<code v-pre>resources/js/bootstrap.js</code> 文件的底部：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">import <span class="token keyword">Echo</span> from <span class="token string double-quoted-string">"laravel-echo"</span></span>
<span class="line"></span>
<span class="line">window<span class="token operator">.</span><span class="token keyword">Echo</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">Echo</span><span class="token punctuation">(</span><span class="token punctuation">{</span></span>
<span class="line">    broadcaster<span class="token punctuation">:</span> <span class="token string single-quoted-string">'pusher'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token argument-name">key</span><span class="token punctuation">:</span> <span class="token string single-quoted-string">'your-pusher-channels-key'</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在创建使用<code v-pre>pusher</code>连接器的 Echo 实例时，你还可以指定<code v-pre>cluster</code>是否必须通过 TLS 进行连接（默认情况下，当<code v-pre>forceTLS</code>为<code v-pre>false</code>时，如果页面是通过 HTTP 加载的，则会生成非 TLS 连接或者作为 TLS 连接失败时的回调）：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">window<span class="token operator">.</span><span class="token keyword">Echo</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">Echo</span><span class="token punctuation">(</span><span class="token punctuation">{</span></span>
<span class="line">    broadcaster<span class="token punctuation">:</span> <span class="token string single-quoted-string">'pusher'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token argument-name">key</span><span class="token punctuation">:</span> <span class="token string single-quoted-string">'your-pusher-channels-key'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token argument-name">cluster</span><span class="token punctuation">:</span> <span class="token string single-quoted-string">'eu'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token argument-name">forceTLS</span><span class="token punctuation">:</span> <span class="token constant boolean">true</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="使用现有客户端实例" tabindex="-1"><a class="header-anchor" href="#使用现有客户端实例"><span>使用现有客户端实例</span></a></h4>
<p>如果你已经有 Echo 使用的 Pusher Channels 或 Socket.io 客户端实例，你可以通过 <code v-pre>client</code> 配置选项将它传递给 Echo：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">const</span> client <span class="token operator">=</span> <span class="token keyword">require</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'pusher-js'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">window<span class="token operator">.</span><span class="token keyword">Echo</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">Echo</span><span class="token punctuation">(</span><span class="token punctuation">{</span></span>
<span class="line">    broadcaster<span class="token punctuation">:</span> <span class="token string single-quoted-string">'pusher'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token argument-name">key</span><span class="token punctuation">:</span> <span class="token string single-quoted-string">'your-pusher-channels-key'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token argument-name">client</span><span class="token punctuation">:</span> client</span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="对事件进行监听" tabindex="-1"><a class="header-anchor" href="#对事件进行监听"><span>对事件进行监听</span></a></h3>
<p>一旦安装并实例化了 Echo，就可以开始监听事件广播了。 首先，使用<code v-pre>channel</code>方法检索频道的实例，然后调用<code v-pre>listen</code>方法来监听指定的事件：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">Echo</span><span class="token operator">.</span><span class="token function">channel</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'orders'</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'OrderShipped'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        console<span class="token operator">.</span><span class="token function">log</span><span class="token punctuation">(</span>e<span class="token operator">.</span>order<span class="token operator">.</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果想在私有频道上收听事件，请使用<code v-pre>private</code>方法。 可以通过链式调用<code v-pre>listen</code>方法，在单个频道上侦听多个事件：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">Echo</span><span class="token operator">.</span><span class="token keyword">private</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'orders'</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token operator">...</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token operator">...</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token operator">...</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="退出频道" tabindex="-1"><a class="header-anchor" href="#退出频道"><span>退出频道</span></a></h3>
<p>要退出频道，你可以在 Echo 实例上调用 <code v-pre>leaveChannel</code> 方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">Echo</span><span class="token operator">.</span><span class="token function">leaveChannel</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'orders'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>如果你想推出一个频道以及相关的私有和在线频道，你可以调用<code v-pre>leave</code>方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">Echo</span><span class="token operator">.</span><span class="token function">leave</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'orders'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="命名空间" tabindex="-1"><a class="header-anchor" href="#命名空间"><span>命名空间</span></a></h3>
<p>你可能已经在上面的示例中，注意到我们没有为事件类指定完整的命名空间。 这是因为 Echo 会自动假设事件位于<code v-pre>App\Events</code>命名空间中。 但是，你可以通过传递 <code v-pre>namespace</code> 配置选项来实例化 Echo 时配置根命名空间：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">window<span class="token operator">.</span><span class="token keyword">Echo</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">Echo</span><span class="token punctuation">(</span><span class="token punctuation">{</span></span>
<span class="line">    broadcaster<span class="token punctuation">:</span> <span class="token string single-quoted-string">'pusher'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token argument-name">key</span><span class="token punctuation">:</span> <span class="token string single-quoted-string">'your-pusher-channels-key'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token keyword">namespace</span><span class="token punctuation">:</span> <span class="token string single-quoted-string">'App.Other.Namespace'</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>或者，你可以在使用 Echo 订阅事件类时使用 <code v-pre>.</code> 作为前缀。 这将允许你始终指定完全限定的类名：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">Echo</span><span class="token operator">.</span><span class="token function">channel</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'orders'</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'.Namespace\\Event\\Class'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">//</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="presence-频道" tabindex="-1"><a class="header-anchor" href="#presence-频道"><span>Presence 频道</span></a></h2>
<p>Presence 频道建立在私有频道安全性的基础上，同时暴露了谁订阅频道的附加特征。 这样可以轻松构建功能强大的协作应用程序功能，例如在其他用户查看同一页面时通知用户。</p>
<h3 id="授权-presence-频道" tabindex="-1"><a class="header-anchor" href="#授权-presence-频道"><span>授权 Presence 频道</span></a></h3>
<p>所有在线频道也是私有频道；因此，用户必须 <a href="#authorizing-channels">被授权才能访问</a>。但是，在为 Presence 频道定义授权回调时，如果用户有权加入该频道，则不会返回<code v-pre>true</code>。 相反，你应该返回有关用户的数据数组。</p>
<p>授权回调返回的数据将可供 JavaScript 应用程序中的 Presence 频道事件侦听器使用。 如果用户未被授权加入Presence 频道，则应返回<code v-pre>false</code>或<code v-pre>null</code>：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Broadcast</span><span class="token operator">::</span><span class="token function">channel</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'chat.{roomId}'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token variable">$user</span><span class="token punctuation">,</span> <span class="token variable">$roomId</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">canJoinRoom</span><span class="token punctuation">(</span><span class="token variable">$roomId</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'id'</span> <span class="token operator">=></span> <span class="token variable">$user</span><span class="token operator">-></span><span class="token property">id</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'name'</span> <span class="token operator">=></span> <span class="token variable">$user</span><span class="token operator">-></span><span class="token property">name</span><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="加入-presence-频道" tabindex="-1"><a class="header-anchor" href="#加入-presence-频道"><span>加入 Presence 频道</span></a></h3>
<p>加入Presence 频道，你可以使用 Echo 的<code v-pre>join</code>方法。 <code v-pre>join</code>方法将返回一个<code v-pre>PresenceChannel</code>实现，它与 <code v-pre>listen</code> 方法一起展示，允许你订阅 <code v-pre>here</code>，<code v-pre>join</code>和<code v-pre>leaving</code>事件。</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">Echo</span><span class="token operator">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string backtick-quoted-string">`chat.${roomId}`</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">.</span><span class="token function">here</span><span class="token punctuation">(</span><span class="token punctuation">(</span>users<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">//</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">.</span><span class="token function">joining</span><span class="token punctuation">(</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        console<span class="token operator">.</span><span class="token function">log</span><span class="token punctuation">(</span>user<span class="token operator">.</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">.</span><span class="token function">leaving</span><span class="token punctuation">(</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        console<span class="token operator">.</span><span class="token function">log</span><span class="token punctuation">(</span>user<span class="token operator">.</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>一旦成功加入频道，将立即执行<code v-pre>here</code>回调，并且将接收包含当前订阅该频道的所有其他用户的用户信息的数组。 当新用户加入频道时，将执行<code v-pre>join</code>方法，而当用户离开频道时，将执行<code v-pre>leaving</code>方法。</p>
<h3 id="广播到-presence-频道" tabindex="-1"><a class="header-anchor" href="#广播到-presence-频道"><span>广播到 Presence 频道</span></a></h3>
<p>Presence 频道可以像公共或私私有频道一样接收事件。 使用聊天室的示例，我们可能希望将<code v-pre>NewMessage</code>事件广播到房间的 Presence 频道。 为此，我们将从事件的<code v-pre>broadcastOn</code>方法返回一个 <code v-pre>PresenceChannel</code> 实例：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 获取事件广播的频道。</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@return</span> <span class="token class-name">Channel<span class="token punctuation">|</span><span class="token keyword">array</span></span></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">broadcastOn</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">PresenceChannel</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'room.'</span><span class="token operator">.</span><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">message</span><span class="token operator">-></span><span class="token property">room_id</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>与公共或私有事件一样，可以使用<code v-pre>广播</code>功能来广播 Presence 频道事件。 与其他事件一样，你可以使用<code v-pre>toOthers</code>方法排除当前用户接收广播：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token function">broadcast</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">NewMessage</span><span class="token punctuation">(</span><span class="token variable">$message</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token function">broadcast</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">NewMessage</span><span class="token punctuation">(</span><span class="token variable">$message</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">toOthers</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>你可以通过 Echo 的<code v-pre>listen</code>方法监听 join 事件：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">Echo</span><span class="token operator">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string backtick-quoted-string">`chat.${roomId}`</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">.</span><span class="token function">here</span><span class="token punctuation">(</span><span class="token operator">...</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">.</span><span class="token function">joining</span><span class="token punctuation">(</span><span class="token operator">...</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">.</span><span class="token function">leaving</span><span class="token punctuation">(</span><span class="token operator">...</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'NewMessage'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">//</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="客户端事件" tabindex="-1"><a class="header-anchor" href="#客户端事件"><span>客户端事件</span></a></h2>
<blockquote>
<p>{提示} 使用 <a href="https://pusher.com/channels" target="_blank" rel="noopener noreferrer">Pusher 频道</a>时， 必须在<a href="https://dashboard.pusher.com/" target="_blank" rel="noopener noreferrer">应用程序仪表板</a>的<code v-pre>应用程序设置</code>部分启用<code v-pre>客户端事件</code>选项以便发送客户端事件。</p>
</blockquote>
<p>有时，你可能希望将事件广播到其他连接的客户端，而根本不需要使用 Laravel 应用程序。 这对于诸如<code v-pre>键入</code>通知之类的内容特别有用，在这种情况下，你希望提醒应用程序的用户另一个用户正在给定屏幕上键入消息。</p>
<p>要广播客户端事件，可以使用 Echo 的<code v-pre>whisper</code>方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">Echo</span><span class="token operator">.</span><span class="token keyword">private</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'chat'</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">.</span><span class="token function">whisper</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'typing'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span></span>
<span class="line">        name<span class="token punctuation">:</span> this<span class="token operator">.</span>user<span class="token operator">.</span>name</span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>要监听客户端事件，可以使用<code v-pre>listenForWhisper</code>方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">Echo</span><span class="token operator">.</span><span class="token keyword">private</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'chat'</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">.</span><span class="token function">listenForWhisper</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'typing'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        console<span class="token operator">.</span><span class="token function">log</span><span class="token punctuation">(</span>e<span class="token operator">.</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="消息通知" tabindex="-1"><a class="header-anchor" href="#消息通知"><span>消息通知</span></a></h2>
<p>通过将事件广播与<a href="https://learnku.com/docs/laravel/6.x/notifications" target="_blank" rel="noopener noreferrer">通知</a>配对，你的 JavaScript 应用程序可以在发生时收到新通知，而无需刷新页面。 首先，请务必阅读有关使用<a href="https://learnku.com/docs/laravel/6.x/notifications#broadcast-notifications" target="_blank" rel="noopener noreferrer">广播通知频道</a> 的文档。</p>
<p>配置通知以使用广播频道后，你可以使用 Echo 的 <code v-pre>notification</code>方法监听广播事件。 请记住，频道名称应与接收通知的实体的类名相匹配：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">Echo</span><span class="token operator">.</span><span class="token keyword">private</span><span class="token punctuation">(</span><span class="token string backtick-quoted-string">`App.User.${userId}`</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">.</span><span class="token function">notification</span><span class="token punctuation">(</span><span class="token punctuation">(</span>notification<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        console<span class="token operator">.</span><span class="token function">log</span><span class="token punctuation">(</span>notification<span class="token operator">.</span>type<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在此示例中，回调将接收通过 <code v-pre>广播</code> 频道发送到 <code v-pre>App\User</code> 实例的所有通知。 <code v-pre>App.User.{id}</code> 频道的频道授权回调包含在 Laravel 框架附带的默认<code v-pre>BroadcastServiceProvider</code>中。</p>
<blockquote>
<p>本译文仅用于学习和交流目的，转载请务必注明文章译者、出处、和本文链接<br>
我们的翻译工作遵照 <a href="https://learnku.com/docs/guide/cc4.0/6589" target="_blank" rel="noopener noreferrer">CC 协议</a>，如果我们的工作有侵犯到您的权益，请及时联系我们。</p>
</blockquote>
<hr>
<blockquote>
<p>原文地址：<a href="https://learnku.com/docs/laravel/6.x/broadcasting/5159" target="_blank" rel="noopener noreferrer">https://learnku.com/docs/laravel/6.x/bro...</a></p>
<p>译文地址：<a href="https://learnku.com/docs/laravel/6.x/broadcasting/5159" target="_blank" rel="noopener noreferrer">https://learnku.com/docs/laravel/6.x/bro...</a></p>
</blockquote>
</div></template>


